﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using RouterControl.Whs;
using RouterControl.Whs.Wizards;

namespace RouterControl.WhsAddIn.Wizards.EditPortForwarding
{
    internal partial class EditPortForwardingClient : WizardPageClientBannerTop
    {
        private readonly log4net.ILog _log = log4net.LogManager.GetLogger(typeof(EditPortForwardingClient));

        private WizardMain ParentWizard2
        {
            get { return (WizardMain)this.ParentWizard; }
        }

        public EditPortForwardingClient()
        {
            InitializeComponent();
        }

        private void whsMachinesCombo_DropDown(object sender, EventArgs e)
        {
        }

        private void EditPortForwardingClientAndPort_BackButtonClick(object sender, EventArgs e)
        {
            SetCurrentPage<EditPortForwardingPortAndProtocol>();
        }

        private void EditPortForwardingClientAndPort_OkButtonClick(object sender, EventArgs e)
        {
            // make sure a maschine was selected
            string ip = null;

            if (this.machineByWhsRB.Checked)
            {
                if (this.whsMachinesCombo.SelectedItem != null)
                {
                    var ce = (Whs.WhsComputers.ClientEntry)this.whsMachinesCombo.SelectedItem;

                    ip = ce.IP;
                }
            }
            else if (this.machineByDnsRB.Checked)
            {
                // wait for lookup
                while (this.lookupDnsSearchTimer.Enabled ||
                       this.lookupDnsBgWorker.IsBusy)
                {
                    System.Threading.Thread.Sleep(100);
                }

                if (!this.dnsSearchResultIP.AnyBlank)
                    ip = this.dnsSearchResultIP.ToString();
            }
            else //if (this.machineByIpRB.Checked)
            {
                if (!this.manualIp.AnyBlank)
                    ip = this.manualIp.ToString();
            }

            if (string.IsNullOrEmpty(ip))
            {
                Microsoft.HomeServer.Controls.QMessageBox.Show(
                    Properties.Resources.txtPortForwardingWizNoIpDesc,
                    Properties.Resources.txtPortForwardingWizNoIpTitle,
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error
                    );

                return;
            }

            // save values
            var fw = this.ParentWizard2.Forwarding.Value;
            
            fw.InternalClient = ip;

            this.ParentWizard2.Forwarding = fw;

            // continue
            SetCurrentPage<EditPortForwardingFinal>();
        }

        private void machineByWhsRB_CheckedChanged(object sender, EventArgs e)
        {
            this.whsMachinesCombo.Enabled = this.machineByWhsRB.Checked;
        }

        private void machineByDnsRB_CheckedChanged(object sender, EventArgs e)
        {
            this.dnsSearchTB.Enabled = this.machineByDnsRB.Checked;

            if (!this.machineByDnsRB.Checked)
                this.lookupDnsSearchTimer.Stop();
        }

        private void machineByIpRB_CheckedChanged(object sender, EventArgs e)
        {
            this.manualIp.Enabled = this.machineByIpRB.Checked;
        }

        private void lookupDnsBgWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            try
            {
                var txt = this.dnsSearchTB.Text;
	
                if (string.IsNullOrEmpty(txt))
                    return;
	
                var ip = Whs.WhsComputers.LookupIpByDns(txt);
	
                e.Result = ip;
            }
            catch (Exception ex)
            {
                _log.Error("Failed to search machine by DNS name", ex);

                // ignore
            }
        }

        public override void StartRealWork()
        {
            base.StartRealWork();

            // load default ip base
            {
                var whsIp = Whs.WhsComputers.GetHomeServerIp();

                if (whsIp != null)
                {
                    if (whsIp.Length > 0)
                        whsIp[whsIp.Length - 1] = 0;

                    this.manualIp.SetAddressBytes(whsIp);
                }
            }

            // load computers
            this.whsMachinesCombo.Items.Clear();

            foreach (var c in Whs.WhsComputers.Instance.LoadComputers())
                this.whsMachinesCombo.Items.Add(c);

            // find computer
            FindCurrentInternalClient();
        }

        private void FindCurrentInternalClient()
        {
            var internalIp = this.ParentWizard2.Forwarding.Value.InternalClient;

            if (string.IsNullOrEmpty(internalIp))
                return;

            // search for known computers first
            var internalIpWhs = Enumerable.FirstOrDefault<WhsComputers.ClientEntry?>((
                                                                                from Whs.WhsComputers.ClientEntry e in this.whsMachinesCombo.Items
                                                                                where internalIp == e.IP
                                                                                select (Whs.WhsComputers.ClientEntry?)e
                                                                            ));

            if (internalIpWhs.HasValue)
            {
                this.whsMachinesCombo.SelectedItem = internalIpWhs.Value;
                this.machineByWhsRB.Checked = true;

                return;
            }

            // set ip then
            try
            {
                this.manualIp.Text = internalIp;
                this.machineByIpRB.Checked = true;
            }
            catch (Exception ex)
            {
                _log.Error("Failed to parse port forwarding IP: " + internalIp, ex);

                // ignore
            }
        }

        private void lookupDnsBgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Result != null)
            {
                this.dnsSearchResultIP.SetAddressBytes((byte[])e.Result);
            }
            else
            {
                this.dnsSearchResultIP.Clear();
            }

            this.lookupDnsStatusImage.Visible = false;
        }

        private void dnsSearchTB_TextChanged(object sender, EventArgs e)
        {
            this.lookupDnsSearchTimer.Stop();
            this.lookupDnsSearchTimer.Start();
        }

        private void lookupDnsSearchTimer_Tick(object sender, EventArgs e)
        {
            this.lookupDnsSearchTimer.Stop();

            this.lookupDnsStatusImage.Visible = true;

            this.lookupDnsBgWorker.RunWorkerAsync();
        }
    }
}